﻿using System;
using System.Collections.Generic;
using XCommunity.Data;
using XCommunity.Documents;
using System.Data;
using System.Security.Principal;

namespace XCommunity.Frames
{

  /// <summary>
  /// 框架服务
  /// </summary>
  /// <remarks>
  /// 框架服务负责管理话题框架对象，并提供框架基础服务（例如发布文档等）。
  /// </remarks>
  public class FrameService
  {

    private ICommunityContext _context;

    //private BoardPersister _boardPersister;

    private TopicPersister _topicPersister;


    private TopicMetaCache _topicMetaCache;
    private TopicFrameCache _topicFrameCache;


    /// <summary>
    /// 创建框架服务实例
    /// </summary>
    /// <param name="context"></param>
    public FrameService( ICommunityContext context )
    {
      _context = context;


      //_boardPersister = new BoardPersister();

      _topicPersister = new TopicPersister();

      _topicMetaCache = new TopicMetaCache( this );
      _topicFrameCache = new TopicFrameCache( this );

    }

    /// <summary>
    /// 初始化服务
    /// </summary>
    public virtual void Init()
    {
      _topicMetaCache.Init( Context.CacheService );
      _topicFrameCache.Init( Context.CacheService );
    }

    /// <summary>
    /// 当前上下文实例
    /// </summary>
    public ICommunityContext Context
    {
      get { return _context; }
    }

    /*
    /// <summary>
    /// 版面（Board）持久化对象
    /// </summary>
    public virtual BoardPersister BoardPersister
    {
      get { return _boardPersister; }
    }
    */

    /// <summary>
    /// 话题（Topic）持久化对象
    /// </summary>
    public virtual TopicPersister TopicPersister
    {
      get { return _topicPersister; }
    }


    /// <summary>
    /// 话题元数据缓存
    /// </summary>
    public virtual TopicMetaCache TopicMetaCache
    {
      get { return _topicMetaCache; }
    }


    /// <summary>
    /// 话题框架的缓存
    /// </summary>
    public virtual TopicFrameCache TopicFrameCache
    {
      get { return _topicFrameCache; }
    }


    /// <summary>
    /// 获取话题框架对象
    /// </summary>
    /// <param name="topicId">话题ID</param>
    /// <returns></returns>
    public virtual ITopicFrame GetTopicFrame( int topicId )
    {
      return TopicFrameCache.GetOrLoadTopic( topicId, id => TopicPersister.LoadTopicFrame( this, GetTopicMeta( id ) ) );
    }



    /// <summary>
    /// 获取话题元数据
    /// </summary>
    /// <param name="topicId"></param>
    /// <returns></returns>
    public virtual TopicMeta GetTopicMeta( int topicId )
    {
      TopicMeta meta = TopicMetaCache.GetTopicMeta( topicId );

      if ( meta == null )
        TopicMetaCache.AddItem( meta = TopicPersister.LoadTopicMeta( topicId ) );

      return meta;
    }


    /*
    private IDictionary<string, BoardFrame> _boards;

    /// <summary>
    /// 所有加载的版面集合
    /// </summary>
    public IDictionary<string, BoardFrame> Boards
    {
      get
      {
        if ( _boards == null )
          InitializeBoards();

        return _boards;
      }
    }


    /// <summary>
    /// 初始化所有版面
    /// </summary>
    /// <returns></returns>
    protected virtual IDictionary<string, BoardFrame> InitializeBoards()
    {

      string configUri = "file:///C:/XCommunity/Boards.xml";

      return _boards = BoardPersister.LoadBoards( this, configUri );
    }

     
      
      
      
    private PracticalBoardFrame _defaultForum;

    public PracticalBoardFrame DefaultForum
    {
      get
      {
        throw new NotImplementedException();
      }
    }
    */



    private sealed class PublishedDocumentKey
    {
      public PublishedDocumentKey( int topicId, int documentId )
      {
        TopicId = topicId;
        DocumentId = documentId;
      }

      public int TopicId
      {
        get;
        private set;
      }

      public int DocumentId
      {
        get;
        private set;
      }

      public override bool Equals( object obj )
      {
        PublishedDocumentKey instance = obj as PublishedDocumentKey;
        if ( instance == null )
          return false;

        return this.TopicId == instance.TopicId && this.DocumentId == instance.DocumentId;
      }

      public override int GetHashCode()
      {
        return DocumentId.GetHashCode();
      }
    }


    private sealed class PublishedDocumentValue
    {
      public PublishedDocumentValue( DateTime publishDate, string method )
      {
        PublishDate = publishDate;
        PublishMethod = method;
      }

      public DateTime PublishDate
      {
        get;
        private set;
      }

      public string PublishMethod
      {
        get;
        private set;
      }
    }


    private Dictionary<PublishedDocumentKey, PublishedDocumentValue> publishedDocumentCache = new Dictionary<PublishedDocumentKey, PublishedDocumentValue>();

    /// <summary>
    /// 获取已发布的文档包装
    /// </summary>
    /// <param name="topic">所属的话题</param>
    /// <param name="documentId">文档ID</param>
    /// <returns>已发布的文档</returns>
    public PublishedDocument GetDocument( ITopicFrame topic, int documentId )
    {

      var key = new PublishedDocumentKey( topic.TopicId, documentId );


      PublishedDocumentValue value;

      if ( !publishedDocumentCache.TryGetValue( key, out value ) )
      {
        DataRow data = TopicFrameDataProvider.DbUtility.ExecuteSingleRow( "SELECT PublishDate, PublishMethod FROM PublishedDocuments WHERE TopicId = {0} AND DocumentId = {1}", topic.TopicId, documentId );

        value = new PublishedDocumentValue( DateTime.SpecifyKind( (DateTime) data["PublishDate"], DateTimeKind.Utc ), (string) data["PublishMethod"] );
        publishedDocumentCache.Add( key, value );
      }

      return new PublishedDocument( topic, documentId, Context.DocumentService, value.PublishDate, value.PublishMethod );
    }



    /// <summary>
    /// 当话题框架发生改变后发生
    /// </summary>
    public event EventHandler<TopicEventArgs> TopicChanged;

    protected internal void OnTopicChanged( object sender, TopicEventArgs e )
    {
      if ( TopicChanged != null )
        TopicChanged( sender, e );
    }



    /// <summary>
    /// 当话题被参与后发生
    /// </summary>
    public event EventHandler<TopicEventArgs> TopicAttached;

    protected internal virtual void OnTopicAttached( object sender, TopicEventArgs e )
    {
      if ( TopicAttached != null )
        TopicAttached( sender, e );
    }


    /// <summary>
    /// 当帖子被修改后发生
    /// </summary>
    public event EventHandler<PostEventArgs> PostModified;

    protected internal virtual void OnPostModified( object sender, PostEventArgs e )
    {
      if ( PostModified != null )
        PostModified( sender, e );
    }



    /// <summary>
    /// 发布一个文档到话题
    /// </summary>
    /// <param name="topic">文档要被发布到的话题</param>
    /// <param name="document">需要被发布的文档</param>
    /// <param name="method">发布的方法或用途</param>
    /// <returns>已发布的文档副本</returns>
    public virtual PublishedDocument PublishDocument( ITopicFrame topic, Document document, string method )
    {
      if ( !document.Meta.Saved )
        throw new ArgumentException( "不能发布未保存的文档", "document" );

      TopicPersister.PublishDocument( topic.TopicId, document.Meta, method );

      return GetDocument( topic, document.Meta.DocumentId );
    }

  }

  public class TopicEventArgs : EventArgs
  {
    public IIdentity Account
    {
      get;
      internal set;
    }

    public ITopicFrame Topic
    {
      get;
      internal set;
    }
  }

  public class PostEventArgs : EventArgs
  {
    public IIdentity Account
    {
      get;
      internal set;
    }

    public IPostFrame Post
    {
      get;
      internal set;
    }
  }


}
